﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Text.RegularExpressions;

namespace TextAnalysisService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                    ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class TextAnalysisService : ITextAnalysisService
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public string[] Top10Words(string url)
        {
            Web2StringSVC.ServiceClient client = new Web2StringSVC.ServiceClient();
            Uri myUri;
            string urlContents;
            if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out myUri))
            {
                urlContents = client.GetWebContent(url);
            }
            else
            {
                urlContents = "None";
            }
            client.Close();
            urlContents = cleanupHtml(urlContents);
            string[] content = urlContents.Trim().Split();
            content = removeNonWordCharacters(content);
            Dictionary<String, int> occurranceMap = arrayToOccurranceMap(content);
            string[] hi = topTen(occurranceMap);
            return hi;
        }

        private string[] topTen(Dictionary<string, int> occurrances)
        {
            string[] topTen = new string[10];
            if (occurrances.Count < 10)
            {
                occurrances.Keys.CopyTo(topTen, 0);
            }
            else
            {
                List<KeyValuePair<string, int>> myList = occurrances.ToList();
                myList.Sort((firstPair, nextPair) =>
                {
                    return -firstPair.Value.CompareTo(nextPair.Value);
                }
                );
                var topTenKeys = myList.Take(10).ToList();
                for (int i = 0; i < 10; i++)
                {
                    topTen[i] = topTenKeys[i].Key;
                }
            }
            return topTen;
        }

        /**
         * Removes newlines, everything in a script tag and html
         * markup in a string.
         */
        private string cleanupHtml(string urlContents)
        {
            string contentsToReturn = "";
            contentsToReturn = removeNewlines(urlContents);
            contentsToReturn = removeScriptTags(urlContents);
            contentsToReturn = removeMarkupTags(urlContents);
            return contentsToReturn;
        }

        /**
         * Takes an array and creates a Dictionary that has the entries of the array
         * as keys and the amount of times that they occur in the array as the values.
         */
        private Dictionary<string, int> arrayToOccurranceMap(string[] array)
        {
            Dictionary<string, int> occurranceMap = new Dictionary<string, int>();
            foreach (string item in array)
            {
                if (occurranceMap.ContainsKey(item.ToLower()))
                {
                    occurranceMap[item.ToLower()] = occurranceMap[item.ToLower()] + 1;
                }
                else
                {
                    occurranceMap.Add(item.ToLower(), 1);
                }
            }
            return occurranceMap;
        }

        private string removeMarkupTags(string str)
        {
            const string pattern = "([<][/]*\\w+[>])|([<](\\S+\\s+)\\S+[>])|[<][\\S+\\s+]+[/][>]|<[^>]+[/]*>";
            Regex regex = new Regex(pattern);
            return regex.Replace(str, "");
        }

        private string removeScriptTags(string str)
        {
            const string pattern = "([<][sS][cC][rR][iI][pP][tT].*[>].*[<][/][sS][cC][rR][iI][pP][tT][>])";
            Regex regex = new Regex(pattern, RegexOptions.Multiline);
            return regex.Replace(str, "");
        }

        private string removeNewlines(string str)
        {
            const string pattern = "[\n|\r|\r\n|\n\r]";
            Regex regex = new Regex(pattern);
            return regex.Replace(str, "");
        }

        private string[] removeNonWordCharacters(String[] str)
        {
            List<string> output = new List<string>();
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] != "")
                {
                    string strippedString = removeNonWordCharacters(str[i]);
                    if (strippedString != "")
                    {
                        output.Add(strippedString);
                    }
                }
            }
            return output.ToArray();
        }

        private string removeNonWordCharacters(string str)
        {
            const string pattern = "^\\W$";
            Regex regex = new Regex(pattern);
            return regex.Replace(str, "");
        }
    }
}
